﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;

namespace leapt.Repositories
{
    using System.Threading.Tasks;
    using static DbFactory;

    /// <summary>
    /// 泛型仓储基类实现
    /// </summary>
    /// <typeparam name="T">泛型实体类</typeparam>
    public abstract class GenericRepository<T> : IDependency, IRepository<T> where T : class, new()
    {
        #region Implementation of IRepository<T>

        #region 查

        /// <summary>
        /// 根据主值查询单条数据
        /// </summary>
        /// <param name="pkValue">主键值</param>
        /// <returns>泛型实体</returns>
        public T FindById(object pkValue)
        {
            return DB.Queryable<T>().InSingle(pkValue);
        }

        /// <summary>
        /// 查询所有数据(无分页,请慎用)
        /// </summary>
        /// <returns></returns>
        public IEnumerable<T> FindAll()
        {
            return DB.Queryable<T>().ToList();
        }

        /// <summary>
        /// 异步查询所有数据(无分页,请慎用)
        /// </summary>
        /// <returns></returns>
        public async Task<List<T>> FindAllAsync()
        {
            return await DB.Queryable<T>().ToListAsync();
        }

        /// <summary>
        /// 根据条件查询数据
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <param name="orderBy">排序</param>
        /// <returns>泛型实体集合</returns>
        public IEnumerable<T> FindListByClause(Expression<Func<T, bool>> predicate, string orderBy)
        {
            return DB.Queryable<T>().Where(predicate).ToList();
        }

        /// <summary>
        /// 异步根据条件查询数据
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <param name="orderBy">排序</param>
        /// <returns>泛型实体集合</returns>
        public async Task<IEnumerable<T>> FindListByClauseAsync(Expression<Func<T, bool>> predicate, string orderBy)
        {
            return await DB.Queryable<T>().Where(predicate).ToListAsync();
        }

        /// <summary>
        /// 根据条件查询数据
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <returns></returns>
        public T FindByClause(Expression<Func<T, bool>> predicate)
        {
            return DB.Queryable<T>().First(predicate);
        }

        /// <summary>
        /// 异步根据条件查询数据
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <returns></returns>
        public async Task<T> FindByClauseAsync(Expression<Func<T, bool>> predicate)
        {
            return await DB.Queryable<T>().FirstAsync(predicate);
        }

        #endregion

        #region 增

        /// <summary>
        /// 写入实体数据
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns></returns>
        public long Insert(T entity)
        {
            return DB.Insertable(entity).ExecuteReturnBigIdentity();
        }

        /// <summary>
        /// 异步写入实体数据
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns></returns>
        public async Task<long> InsertAsync(T entity)
        {
            return await DB.Insertable(entity).ExecuteReturnBigIdentityAsync();
        }

        #endregion

        #region 改

        /// <summary>
        /// 更新实体数据
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool Update(T entity)
        {
            return DB.Updateable(entity).ExecuteCommand() > 0 ? true : false;
        }

        /// <summary>
        /// 异步更新实体数据
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(T entity)
        {
            return await DB.Updateable(entity).ExecuteCommandAsync() > 0 ? true : false;
        }

        #endregion

        #region 删

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns></returns>
        public bool Delete(T entity)
        {
            return DB.Deleteable(entity).ExecuteCommand() > 0 ? true : false;
        }

        /// <summary>
        /// 异步删除数据
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns></returns>
        public async Task<bool> DeleteAysnc(T entity)
        {
            return await DB.Deleteable(entity).ExecuteCommandAsync() > 0 ? true : false;
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="where">过滤条件</param>
        /// <returns></returns>
        public bool Delete(Expression<Func<T, bool>> @where)
        {
            return DB.Deleteable<T>(@where).ExecuteCommand() > 0 ? true : false;
        }

        /// <summary>
        /// 异步删除数据（动态条件）
        /// </summary>
        /// <param name="where">过滤条件</param>
        /// <returns></returns>
        public async Task<bool> DeleteAysnc(Expression<Func<T, bool>> @where)
        {
            return await DB.Deleteable<T>(@where).ExecuteCommandAsync() > 0 ? true : false;
        }

        /// <summary>
        /// 删除指定ID的数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool DeleteById(object id)
        {
            return DB.Deleteable<T>(id).ExecuteCommand() > 0 ? true : false;
        }

        /// <summary>
        /// 异步删除指定ID的数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteByIdAysnc(object id)
        {
            return await DB.Deleteable<T>(id).ExecuteCommandAsync() > 0 ? true : false;
        }

        /// <summary>
        /// 删除指定ID集合的数据(批量删除)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public bool DeleteByIds(object[] ids)
        {
            return DB.Deleteable<T>().In(ids).ExecuteCommand() > 0 ? true : false;
        }

        /// <summary>
        /// 异步删除指定ID集合的数据(批量删除)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<bool> DeleteByIdsAysnc(object[] ids)
        {
            return await DB.Deleteable<T>().In(ids).ExecuteCommandAsync() > 0 ? true : false;
        }
        #endregion

        #endregion
    }
}
